﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using FreightSoft.Models;
using FreightSoft.Classes;
using FreightSoft.BusinessLogicLayer.ROUTE;

namespace FreightSoft.Controllers
{
    public class ShipmentScheduleController : Controller
    {
        private Entities db = new Entities();
        private OzekiSMS sms = new OzekiSMS();
        private Mail email = new Mail();
         
        //
        // GET: /ShipmentSchedule/

        public ActionResult Index()
        {
            //var customer_order = db.CUSTOMER_ORDER.Include(c => c.CUSTOMER).Include(c => c.FORWARDER).Include(c => c.PORT).Include(c => c.PORT1).OrderBy(x => x.ORDER_ID);
            var shipment_schedule = db.SHIPMENTSCHEDULEs.Include(s => (int)s.SCHEDULEID).Include(s => s.ORIGINPORT).Include(s => s.DESTINATIONPORT).Include(s => s.ROUTEID).Include(s => s.STATUS).OrderBy(s => s.SCHEDULEID);
            return View(db.SHIPMENTSCHEDULEs.ToList());
        }

        //
        // GET: /ShipmentSchedule/Details/5

        public ActionResult Details(int id )
        {
            SHIPMENTSCHEDULE shipmentschedule = db.SHIPMENTSCHEDULEs.Find(id);
            PORT Org_port = db.PORTs.Find(shipmentschedule.ORIGINPORT);
            PORT dest_port = db.PORTs.Find(shipmentschedule.DESTINATIONPORT);
            ROUTE route = db.ROUTEs.Find(shipmentschedule.ROUTEID,1);      
      
            shipmentschedule.ORIGINPORT = Org_port.PORT_NAME.ToString();
            shipmentschedule.DESTINATIONPORT = dest_port.PORT_NAME.ToString();
            shipmentschedule.ROUTEID = route.ROUTE_ID.ToString();
            ViewBag.ORIGINPORT = Org_port.PORT_NAME.ToString();
            ViewBag.DESTINATIONPORT = dest_port.PORT_NAME.ToString();
            ViewBag.ROUTEID = route.ROUTE_ID.ToString();
            if (shipmentschedule == null)
            {
                return HttpNotFound();
            }
            decimal d = (decimal)id;
            IEnumerable<SHIPMENT> shipments = db.SHIPMENTs.Where(s => s.SCHEDULEID == d).ToList();
            ViewBag.SCHEDULEID = shipmentschedule.SCHEDULEID;
            return View(shipments);
        }

        //
        // GET: /ShipmentSchedule/Create

        public ActionResult Create()
        {

            var port_list = db.PORTs.ToList();
            foreach (var i in port_list)
            {
                i.PORT_ID = i.PORT_ID.Trim();
            }
            var PortList = port_list;
            var dropdownList = new SelectList(PortList, "Port_Id", "Port_Name");
            ViewData["Org_Port_ID"] = dropdownList;
            ViewData["Dest_Port_ID"] = dropdownList;

            var ship_list = db.SHIPs.ToList();
            foreach (var i in ship_list)
            {
                i.SHIPID = i.SHIPID.Trim();
            }
            var shiplist = ship_list;
            var shipdropdownlist = new SelectList(shiplist, "ShipId", "S1");
            ViewData["Ship_Id"] = shipdropdownlist;

            var route_list = db.ROUTEs.ToList();
            foreach (var i in route_list)
            {
                i.ROUTE_ID = i.ROUTE_ID.Trim();
            }
            var routeList = route_list;
            var routedropdownlist = new SelectList(routeList, "Route_Id", "Route_Id");
            ViewData["Route_Id"] = routedropdownlist;

            ViewBag.SHIPID = new SelectList(db.SHIPs, "Ship_Id", "S1");
            ViewBag.ORIGINPORT = new SelectList(db.PORTs, "Org_Port_Id", "Port_Name");
            ViewBag.DESTINATIONPORT = new SelectList(db.PORTs, "Dest_Port_Id", "Port_Name");
            ViewBag.ROUEID = new SelectList(db.ROUTEs, "Route_Id", "Route_Id");


            return View();

        }

        //
        // POST: /ShipmentSchedule/Create

        [HttpPost]
        public ActionResult Create(SHIPMENTSCHEDULE shipmentschedule, FormCollection collection )
        {
            if (ModelState.IsValid)
            {
                TrackingController track = new TrackingController();
                shipmentschedule.ORIGINPORT = collection.Get("selectedOriginPortId");
                shipmentschedule.DESTINATIONPORT = collection.Get("selectedDestPortId");
                shipmentschedule.SHIPID = collection.Get("selectedShipId");
                shipmentschedule.ROUTEID = collection.Get("selectedRouteId");
                var idd = db.SHIPMENTSCHEDULEs.Count();
                var my1 = idd + 1002;

                shipmentschedule.SCHEDULEID = my1;
                shipmentschedule.STATUS = "Planned";
                shipmentschedule.S2 = DateTime.Now.ToString();
                int hours = 0;
                double days = 0;

                // CALCULATE planneddelivery date here
                if (shipmentschedule.PLANNED_START_DATE.HasValue)
                {
                    hours = track.calculateTime(shipmentschedule.ORIGINPORT, shipmentschedule.DESTINATIONPORT);
                    days =  hours / 24;
                    DateTime planned = shipmentschedule.PLANNED_START_DATE ?? DateTime.Now;
                    planned = planned.AddDays(days);
                    shipmentschedule.PLANNED_END_DATE = planned;                    
                }               

                // ******
                db.SHIPMENTSCHEDULEs.Add(shipmentschedule);
                db.SaveChanges();

                //return View(shipmentschedule);
                //return RedirectToAction("ReservationSummery", "Reservation", new { HotelName = name, CustomerId = custId, FirstName = customer.FirstName });
                return RedirectToAction("Details", new { Id = shipmentschedule.SCHEDULEID });
            }

            return View(shipmentschedule);
        }

        //
        // GET: /ShipmentSchedule/Edit/5

        public ActionResult Edit(decimal id = 0)
        {
            SHIPMENTSCHEDULE shipmentschedule = db.SHIPMENTSCHEDULEs.Find(id);
            if (shipmentschedule == null)
            {
                return HttpNotFound();
            }
            return View(shipmentschedule);
        }

        //
        // POST: /ShipmentSchedule/Edit/5

        [HttpPost]
        public ActionResult Edit(SHIPMENTSCHEDULE shipmentschedule)
        {
            if (ModelState.IsValid)
            {
                db.Entry(shipmentschedule).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(shipmentschedule);
        }

        //
        // GET: /ShipmentSchedule/Delete/5

        public ActionResult Delete(decimal id = 0)
        {
            SHIPMENTSCHEDULE shipmentschedule = db.SHIPMENTSCHEDULEs.Find(id);
            if (shipmentschedule == null)
            {
                return HttpNotFound();
            }
            return View(shipmentschedule);
        }

        //
        // POST: /ShipmentSchedule/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(decimal id)
        {
            SHIPMENTSCHEDULE shipmentschedule = db.SHIPMENTSCHEDULEs.Find(id);
            db.SHIPMENTSCHEDULEs.Remove(shipmentschedule);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        public ActionResult AddShipments(decimal schedule_id, string route_id)
        {
            List<SHIPMENT> shipments_list = GetShipmentsForTransport(route_id);
            //return View(shipments.ToList());
            ViewBag.SCHEDULE_ID = schedule_id;
            TempData["list"] = shipments_list.ToList();
            return RedirectToAction("AddShipments", "Shipment", new { schedule_id = schedule_id });
            //return View();
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }

        // get shipments that are ready for shipment - from given place to another 
        protected List<SHIPMENT> GetShipmentsForTransport(string route_id)
        {
            var port_list = from route in db.ROUTEs
                            where (route.ROUTE_ID == route_id)
                            select route.PORT_ID;
                            //select route;
            var my = port_list.ToList();
            var my1 = port_list.Count();
            var records = from shipments in db.SHIPMENTs
                          where (port_list.Contains(shipments.ORIGINPORT)) && (port_list.Contains(shipments.DESTINATIONPORT))
                          && (shipments.STATUS == "Released") && (shipments.SCHEDULEID == null)
                          select shipments;
            var tt = records.ToList();
            var yy = records.Count();
            //List<SHIPMENT> records = new List<SHIPMENT>();
            return records.ToList();
        }
        // ************

        public decimal GetTotalVolumeOfSchedule(decimal schedule_id)
        {
            SHIPMENTSCHEDULE schedule = db.SHIPMENTSCHEDULEs.Find(schedule_id);
            var records = from shipments in db.SHIPMENTs
                          where ((shipments.STATUS == "OnBoard") || (shipments.STATUS == "InTransit"))
                          && (shipments.SCHEDULEID == schedule_id)
                          select shipments;
            //decimal tot_weight = 0;
            decimal tot_volume = 0;
            foreach (var i in records)
            {
               // tot_weight += i.WEIGHT;
                tot_volume += i.VOLUME ?? 0;
            }
            return tot_volume;
        }

        public decimal GetTotalWeightOfSchedule(decimal schedule_id)
        {
            SHIPMENTSCHEDULE schedule = db.SHIPMENTSCHEDULEs.Find(schedule_id);
                   //   // IQueryable<SHIPMENT> shipments = db.SHIPMENTs.Where(p => p.SCHEDULEID == schedule_id);
        //  // consider only the shipments that are in the ship
          var records = from shipments in db.SHIPMENTs
                          where ((shipments.STATUS == "OnBoard") || (shipments.STATUS == "InTransit"))
                          && (shipments.SCHEDULEID == schedule_id)
                          select shipments;
            
            decimal tot_weight = 0;
            //decimal tot_volume = 0;
            foreach (var i in records)
            {
                if ( i.WEIGHT != null)
                tot_weight += i.WEIGHT ?? 0;
                //tot_volume += i.VOLUME;
            }
            return tot_weight;
        }

        // *******************
        public ActionResult Plan(int id)
        {
            SHIPMENTSCHEDULE shipmentschedule = db.SHIPMENTSCHEDULEs.Find(id);
            shipmentschedule.STATUS = "Planned";
            shipmentschedule.S2 = DateTime.Now.ToString();
            db.SaveChanges();
            return RedirectToAction("Details", new { id = id });
        }


        public ActionResult Release(int id)
        {
            SHIPMENTSCHEDULE shipmentschedule = db.SHIPMENTSCHEDULEs.Find(id);
            ShipmentController shipment_record = new ShipmentController();
            shipmentschedule.STATUS = "Released";
            shipmentschedule.S2 = DateTime.Now.ToString();
            db.SaveChanges();
            decimal scheduleid= (decimal) id;
            IQueryable<SHIPMENT> shipments = db.SHIPMENTs.Where(s => s.SCHEDULEID == (decimal) id);
            foreach (var i in shipments)
            {
                i.STATUS = "InTransit";
                db.SaveChanges();
                LinesInTransit(i.SHIPMENTID);
            }

            return RedirectToAction("Details", new { id = id });
        }
        // change the line status to InTrasit
        public void LinesInTransit(decimal shipmentId)
        {
            SHIPMENT shipment = db.SHIPMENTs.Find(shipmentId);
            foreach (var i in shipment.SHIPMENTLINEs)
            {
                i.STATUS = "InTransit";
                db.SaveChanges();
                OrdersInTransit((int)i.ORDERID);
            }
        }
        // change status of connected Customer orders to InTransit
        public void OrdersInTransit(int id)
        {
            CUSTOMER_ORDER order = db.CUSTOMER_ORDER.Find(id);
            order.STATUS = "InTransit"; //should this be SHIPPED???
            db.SaveChanges();
        }

        public ActionResult Cancel(int id)
        {
            SHIPMENTSCHEDULE shipmentschedule = db.SHIPMENTSCHEDULEs.Find(id);
            shipmentschedule.STATUS = "Cancelled";
            shipmentschedule.S2 = DateTime.Now.ToString();
            db.SaveChanges();
            return RedirectToAction("Details", new { id = id });
        }


        public ActionResult Docked(decimal id)
        {
            SHIPMENTSCHEDULE shipmentschedule = db.SHIPMENTSCHEDULEs.Find(id);
            ViewBag.CURRENT_PORT = new SelectList(db.PORTs, "PORT_ID", "PORT_NAME");

            return View(shipmentschedule);
        }

        [HttpPost]
        public ActionResult Docked(int id)
        {
            string port = Request["CURRENT_PORT"];
            //ShipmentController shipment_record = new ShipmentController();
            //SHIPMENTSCHEDULE schedule = db.SHIPMENTSCHEDULEs.Find(shipmentschedule.SCHEDULEID);
            SHIPMENTSCHEDULE schedule = db.SHIPMENTSCHEDULEs.Find(id);
            if (schedule.DESTINATIONPORT == port)
            {
                schedule.STATUS = "Completed";
            }
            else
            {
                schedule.STATUS = "Docked";
            }
            schedule.CURRENT_PORT = port;
            schedule.S2 = DateTime.Now.ToString();
            // Update shipments as delivered if current port == destinations port
            db.SaveChanges();


            IQueryable<SHIPMENT> shipments = db.SHIPMENTs.Where(s => s.SCHEDULEID == schedule.SCHEDULEID);
            foreach (var i in shipments)
            {
                UpdateShipmentDelivered(i.SHIPMENTID, port);
               
            }


            return RedirectToAction("Details", new { id = id });
        }

        public void UpdateShipmentDelivered(decimal shipmentId, string current_port)
        {
            SHIPMENT shipment = db.SHIPMENTs.Find(shipmentId);
            if (shipment.DESTINATIONPORT == current_port)
            {
                shipment.STATUS = "Delivered";
                db.SaveChanges();

                foreach (var i in shipment.SHIPMENTLINEs)
                {
                    i.STATUS = "Delivered";
                    db.SaveChanges();
                    OrdersDelivered((int)i.ORDERID);
                }
            }

        }


        public void OrdersDelivered(int id)
        {
            CUSTOMER_ORDER order = db.CUSTOMER_ORDER.Find(id);
            order.STATUS = "Delivered";
            db.SaveChanges();

            var phnNo = order.CUSTOMER.PHONE;
            sms.SendSMS(phnNo.ToString(), "Your Order " + order.ORDER_ID + " is delivered");
            email.SendOrderArrived(order.CUSTOMER.EMAIL.ToString(), order.ORDER_ID.ToString());
        }
        public ActionResult CurrentPort(int id)
        {
            //Request["dropdownlist"]
            var t = Request["CURRENT_PORT"];
            SHIPMENTSCHEDULE shipmentschedule = db.SHIPMENTSCHEDULEs.Find(id);
            shipmentschedule.STATUS = "Docked";
            shipmentschedule.S2 = DateTime.Now.ToString();
            shipmentschedule.CURRENT_PORT = "";
            // Update shipments as delivered if current port == destinations port
            db.SaveChanges();
            return RedirectToAction("Details", new { id = id });
        }

        // auto complete if curent port == destination port of Schedule
        public ActionResult Complete(int id)
        {
            SHIPMENTSCHEDULE shipmentschedule = db.SHIPMENTSCHEDULEs.Find(id);
            shipmentschedule.STATUS = "Complete";
            shipmentschedule.S2 = DateTime.Now.ToString();
            //sshipmentschedule.CURRENT_PORT = "";
            
            db.SaveChanges();
            return RedirectToAction("Details", new { id = id });
        }

        public ActionResult AutomaticAdd(int id)
        {
            SHIPMENTSCHEDULE shipmentschedule = db.SHIPMENTSCHEDULEs.Find(id);
            List<SHIPMENT> shipments_list = GetShipmentsForTransport(shipmentschedule.ROUTEID);

            foreach (var i in shipments_list)
            { 
                if ((shipmentschedule.SHIP.TOTALVOLUME >= (GetTotalVolumeOfSchedule(id) + i.VOLUME)) &&
                    (shipmentschedule.SHIP.TOTALWEIGHT >= (GetTotalWeightOfSchedule(id) + i.WEIGHT)))
                {
                    i.SCHEDULEID = id;
                    db.SaveChanges();
                }
            }
            return RedirectToAction("Details", new { id = id });
        }

    }
}